/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file vs_manager.c
 * @brief Vendor Specific功能管理模块
 */

#include "nci_feature.h"
#if IS_FEATURE_ON(NCI_FEATURE_VS)

#include "nci_module.h"
#include "nci_task.h"
#include "nci_proprietary.h"
#include "nfa_vs.h"
#include "nfa_discover.h"
#include "nci_transport.h"
#include "nci_utils.h"
#include "discover_int.h"
#include "nfa_utils.h"

#define NCI_ANDROID_OID 0x0C

#define NCI_ANDROID_POWER_SAVING 0x01
#define NCI_ANDROID_OBSERVER_MODE 0x02
#define NCI_ANDROID_GET_OBSERVER_MODE_STATUS 0x04

#define NCI_ANDROID_PROP_RSP_LEN 5
#define NCI_ANDROID_GET_CAP_INDEX_CAP_LEN 7

/**
 * @brief Vendor Specific模块管理context
 */
typedef struct {
    bool ntf_upload_enable;
    bool observe_mode_enabled;
    uint8_t proprietary_lxdebug;
    tNCI_VS_CBACK cback;
    tMUTEX mutex;
} tNCI_VS_MANAGER;

static tNCI_VS_MANAGER s_vs = {
    .ntf_upload_enable = false,
    .observe_mode_enabled = false,
    .proprietary_lxdebug = 0,
    .cback = NULL,
    .mutex = MUTEX_INIT_VAL("vs"),
};

#define GET_VS_LOCK(_fail_action) \
    if (osi_mutex_lock(&s_vs.mutex) != NFC_STATUS_OK) { \
        NFCLOG_E("get lock failed!"); \
        _fail_action; \
    }
#define RELEASE_VS_LOCK() \
    if (osi_mutex_unlock(&s_vs.mutex) != NFC_STATUS_OK) { \
        NFCLOG_E("release lock failed!"); \
    }

/**
 * @brief vs模块允许发送的指令头
 */
const static uint16_t s_white_list[] =  {
    0x2002, /* SET_CONFIG */
    0x2003, /* GET_CONFIG */
    0x2102, /* RF_GET_LISTEN_MODE_ROUTING_CMD */
    0x2F25, /* GET_BL_VERSION */
    0x2F0C, /* ANDROID_PROP_CMD */
};

/**
 * @brief 校验指令包头
 * @param data 需要校验的指令
 * @return 成功返回 true
 */
static bool vs_check_hdr (const uint16_t head) {
    for (uint8_t i = 0; i < sizeof(s_white_list) / sizeof(uint16_t); ++i) {
        if (head == s_white_list[i]) {
            return true;
        }
    }
    return false;
}

/**
 * @brief 校验指令正确性
 * @param data 需要校验的指令
 * @param len 需要校验的指令长度
 * @return 成功返回 true
 */
static bool vs_check_cmd (const uint8_t *data, uint16_t len) {
    /* 校验payload长度 */
    if (data && len >= 3 && (data[2] + NCI_BUF_HEAD_SIZE) == len) {
        uint16_t head = (data[0] << 8) | data[1];
        if (vs_check_hdr(head)) {
            return true;
        }
    }
    NFCLOG_E("failed: len = 0x%x.", len);
    return false;
}

/**
 * @brief 实际发送指令的函数
 * @param[in] cmd 需要发送的tNCI_VS_CMD数组
 * @param[in] num_of_cmd tNCI_VS_CMD数组长度
 * @param[out] rsp 接收最后一条指令的rsp数据
 * @param[in] stop_when_failed 发送指令失败时是否停止
 * @return 发送成功返回NCI_STATUS_OK, 其他 发送失败
 */
static tNCI_STATUS vs_send_cmd_internal(tNCI_VS_CMD *cmd, uint8_t num_of_cmd,
            tNCI_RSP *rsp, bool stop_when_failed) {
    NFCLOG_I("enter");
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    const uint8_t *p_data;
    uint16_t data_len;
    tNCI_BUF *cmd_buf = alloc_nci_buf(0);
    tNCI_BUF *rsp_buf = alloc_nci_buf(0);
    if (!cmd_buf || !rsp_buf) {
        NFCLOG_E("alloc_nci_buf failed!");
        goto cleanup;
    }
    for (uint8_t i = 0; i < num_of_cmd; ++i) {
        NFCLOG_D("sending vendor special cmd[%d].", i);
        p_data = cmd[i].data;
        data_len = cmd[i].len;
        if (vs_check_cmd(p_data, data_len)) {
            /* 每次拼接需要重置nci buf */
            reset_nci_buf(cmd_buf);
            reset_nci_buf(rsp_buf);
            cmd_buf->head.hdr[0] = p_data[0];
            cmd_buf->head.hdr[1] = p_data[1];
            rsp_buf->head = cmd_buf->head;
            rsp_buf->head.mt = NCI_RSP;
            rsp_buf->head.pbf = 0;
            ARRAY_TO_BUF(cmd_buf, p_data + NCI_BUF_HEAD_SIZE, data_len - NCI_BUF_HEAD_SIZE);
            ret = nci_tp_send_nci_get_rsp_wait_ntf(cmd_buf, rsp_buf, NCI_DEFAULT_WAIT_TIME, true, NULL, 0, NULL);
        } else {
            NFCLOG_E("vs_check_cmd failed!");
            ret = NCI_STATUS_EXT_FAILED;
        }
        /* 判断发送指令失败时是否退出 */
        if (ret != NCI_STATUS_OK) {
            if (stop_when_failed) {
                NFCLOG_E("send cmd[%d] failed, return.", i);
                goto cleanup;
            } else if (!stop_when_failed) {
                NFCLOG_W("send cmd[%d] failed, ret = %d, but ignore.", i, ret);
                ret = NCI_STATUS_OK;
            }
        }
    } /* end for */
    if (ret == NCI_STATUS_OK && rsp_buf->data && rsp_buf->len > 0) {
        /* 在调用方释放资源 */
        rsp->data = osi_calloc(rsp_buf->len + NCI_BUF_HEAD_SIZE);
        if (!rsp->data) {
            NFCLOG_E("allocate failed!");
            ret = NCI_STATUS_EXT_FAILED;
            goto cleanup;
        }
        rsp->data[0] = rsp_buf->head.hdr[0];
        rsp->data[1] = rsp_buf->head.hdr[1];
        rsp->data[2] = rsp_buf->len;
        osi_memcpy_s(rsp->data + NCI_BUF_HEAD_SIZE, rsp_buf->len, rsp_buf->data, rsp_buf->len);
        rsp->len = rsp_buf->len + NCI_BUF_HEAD_SIZE;
    }
cleanup:
    free_nci_buf(cmd_buf);
    free_nci_buf(rsp_buf);
    NFCLOG_I("exit! (0x%x)", ret);
    return ret;
}

/**
 * @brief 发送vendor special指令的接口函数
 * @param[in] cmd 需要发送的tNCI_VS_CMD数组
 * @param[in] num_of_cmd tNCI_VS_CMD数组长度
 * @param[out] rsp 接收最后一条指令的rsp数据
 * @param[in] stop_when_failed 发送指令失败时是否停止
 * @param[in] rf_rule 发送指令时RF状态切换规则
 * @return 发送成功返回NCI_STATUS_OK, 其他 发送失败
 */
tNCI_STATUS nfa_vs_send_cmd(tNCI_VS_CMD *cmd, uint8_t num_of_cmd,
            tNCI_RSP *rsp, bool stop_when_failed, tNCI_VS_RFST_RULE rf_rule) {
    OSI_CHK_PARAM_INVALID(num_of_cmd < 1, return NCI_STATUS_INVALID_PARAM);
    OSI_CHK_PARAM_INVALID(!cmd, return NCI_STATUS_INVALID_PARAM);
    OSI_CHK_PARAM_INVALID(!rsp, return NCI_STATUS_INVALID_PARAM);

    GET_VS_LOCK(return NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;

    if (rf_rule == VS_RFST_RULE_ALLOW_ALL) {
        NFCLOG_I("rf_rule = %d, just sending.", rf_rule);
        ret = vs_send_cmd_internal(cmd, num_of_cmd, rsp, stop_when_failed);
        goto unlock;
    }
    /* 其他rf_rule需要获取当前rf状态 */
    if (rf_lock() != NCI_STATUS_OK) {
        NFCLOG_E("rf_lock failed!");
        ret = NCI_STATUS_EXT_GET_LOCK_FAILED;
        goto unlock;
    }
    bool rf_enabled = false, check_result = false;
    tNCI_RFST rf_status = nfa_rf_get_state();
    NFCLOG_I("rf_rule = %d, current state = 0x%x.", rf_rule , rf_status);
    switch (rf_rule) {
        case VS_RFST_RULE_ONLY_IDLE: /* 0 */
            check_result = (rf_status == NCI_RFST_IDLE) ? true : false;
            break;
        case VS_RFST_RULE_DISC_TO_IDLE: /* 1 */
            if (rf_status == NCI_RFST_DISCOVERY) {
                NFCLOG_I("RF state should be IDLE.");
                if (nfa_rf_stop_discovery() != NCI_STATUS_OK) {
                    NFCLOG_E("nfa_rf_stop_discovery failed!");
                    break;
                }
                rf_enabled = true; /* 后续将RF切回DISCOVERY */
                check_result = true;
            }
            /* fall through */
        case VS_RFST_RULE_ALLOW_IDLE_DISC: /* 2 */
            if (rf_status == NCI_RFST_DISCOVERY || rf_status == NCI_RFST_IDLE) {
                check_result = true;
            }
            break;
        default:
            NFCLOG_E("unknown rule type!");
            break;
    }
    if (check_result) {
        ret = vs_send_cmd_internal(cmd, num_of_cmd, rsp, stop_when_failed);
    } else {
        NFCLOG_E("current state does not allow sending cmd!");
    }
    /* 需要恢复DISCOVERY状态 */
    if (rf_enabled) {
        NFCLOG_I("sending finish, restart RF discovery.");
        ret = nfa_rf_start_discovery();
        if (ret != NCI_STATUS_OK) {
            NFCLOG_E("nfa_rf_start_discovery failed!");
        }
    }
    rf_unlock();
unlock:
    RELEASE_VS_LOCK();
    if (ret != NCI_STATUS_OK) {
        nfa_utils_free_rsp(rsp, true);
    }
    return ret;
}

/**
 * @brief 设置LxDebug级别
 * @param[in] level lxdebug级别
 */
void nfa_vs_proprietary_set_lxdebug(uint8_t level) {
    GET_VS_LOCK(return);
    if(!s_vs.ntf_upload_enable) {
        NFCLOG_W("vs not ntf_upload_enable");
        goto unlock;
    }
    s_vs.proprietary_lxdebug = level;
    NFCLOG_I("Set lxdebug = %d", s_vs.proprietary_lxdebug);
unlock:
    RELEASE_VS_LOCK();
}

/**
 * @brief 处理NFCEE_ACTION_INFO事件的函数
 *
 * @param data 事件数据
 * @param data_len 事件数据长度
 * @return 如果成功处理事件，则返回true；否则返回false。
 */
void nci_ee_action_ntf_handle(uint8_t *data, uint16_t data_len) {
    OSI_CHK_PARAM_INVALID(!data, return);
    OSI_CHK_PARAM_INVALID(data_len == 0, return);
    GET_VS_LOCK(return);
    if(!s_vs.ntf_upload_enable || !s_vs.cback) {
        goto unlock;
    }

    tNCI_VS_CONTENT content;
    content.ee_action.len = data_len;
    content.ee_action.data = data;
    s_vs.cback(NCI_VS_EVT_EE_ACTION_INFO, &content);
unlock:
    RELEASE_VS_LOCK();
}

/**
 * @brief 处理Proprietary相关的通知
 *
 * @param oid NTF的Operation ID
 * @param data NTF的payload数据，不包含NCI头
 * @param data_len NTF的payload数据长度
 */
void nci_proprietary_ntf_handle(uint8_t oid, uint8_t *data, uint16_t data_len) {
    OSI_CHK_PARAM_INVALID(!data, return);
    OSI_CHK_PARAM_INVALID(data_len == 0, return);
    GET_VS_LOCK(return);
    if(!s_vs.ntf_upload_enable || !s_vs.cback) {
        goto unlock;
    }

    tNCI_VS_CONTENT content;
    NFCLOG_D("oid = 0x%02X, lxdebug = 0x%02X", oid, s_vs.proprietary_lxdebug);

    switch (oid) {
        case NCI_PROPRIETARY_M1_AUTH_STATUS:
            content.op_info.oid = oid;
            content.op_info.msg.len = data_len;
            content.op_info.msg.data = data;
            s_vs.cback(NCI_VS_EVT_PROPRIETARY_M1_AUTH_STATUS, &content);
            break;

        case NCI_PROPRIETARY_DEBUG_L1:
            if (s_vs.proprietary_lxdebug & PROPRIETARY_DEBUG_L1_MASK) {
                content.op_info.oid = oid;
                content.op_info.msg.len = data_len;
                content.op_info.msg.data = data;
                s_vs.cback(NCI_VS_EVT_PROPRIETARY_LXDEBUG, &content);
            }
            break;

        case NCI_PROPRIETARY_DEBUG_L2:
            if (s_vs.proprietary_lxdebug & PROPRIETARY_DEBUG_L2_MASK) {
                content.op_info.oid = oid;
                content.op_info.msg.len = data_len;
                content.op_info.msg.data = data;
                s_vs.cback(NCI_VS_EVT_PROPRIETARY_LXDEBUG, &content);
            }
            break;

        case NCI_PROPRIETARY_DEBUG_L3:
            if (s_vs.proprietary_lxdebug & PROPRIETARY_DEBUG_L3_MASK) {
                content.op_info.oid = oid;
                content.op_info.msg.len = data_len;
                content.op_info.msg.data = data;
                s_vs.cback(NCI_VS_EVT_PROPRIETARY_LXDEBUG, &content);
            }
            break;

        default:
            NFCLOG_W("Not require NCI_PROPRIETARY_NTF oid: 0x%02X", oid);
            break;
    }
unlock:
    RELEASE_VS_LOCK();
}

/**
 * @brief 设置Observe Mode状态
 *
 * @param enable true: 开启Observe Mode, false: 关闭Observe Mode
 * @return 设置成功返回NCI_STATUS_OK, 其他 设置失败
 */
tNCI_STATUS nfa_vs_set_observe_mode(bool enable) {
    GET_VS_LOCK(return NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    tNCI_RSP rsp = {0};
    if (s_vs.observe_mode_enabled == enable) {
        NFCLOG_W("observe mode is already %s", enable ? "enabled" : "disabled");
        ret = NCI_STATUS_OK;
        goto unlock;
    }
    uint8_t raw_nci[] = {0x2F, 0x0C, 0x02, NCI_ANDROID_OBSERVER_MODE, enable ? 0x01 : 0x00};
    tNCI_VS_CMD cmd = {
        .data = raw_nci,
        .len = sizeof(raw_nci),
    };

    ret = nfa_vs_send_cmd(&cmd, 1, &rsp, true, VS_RFST_RULE_DISC_TO_IDLE);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_vs_send_cmd failed, ret = %d", ret);
        goto unlock;
    }
    if (rsp.data && (rsp.len == NCI_ANDROID_PROP_RSP_LEN)) {
        ret = rsp.data[NCI_ANDROID_PROP_RSP_LEN - 1];
    } else {
        ret = NCI_STATUS_EXT_FAILED;
        NFCLOG_E("rsp data is invalid, len = %d", rsp.len);
    }
unlock:
    if (ret == NCI_STATUS_OK) {
        s_vs.observe_mode_enabled = enable;
    }
    RELEASE_VS_LOCK();
    nfa_utils_free_rsp(&rsp, true);
    return ret;
}
/**
 * @brief 获取Observe Mode状态
 *
 * @return true: Observe Mode开启, false: Observe Mode关闭
 */
bool nfa_vs_is_observe_mode_enabled() {
    GET_VS_LOCK(return false);
    bool is_enabled = s_vs.observe_mode_enabled;
    RELEASE_VS_LOCK();
    return is_enabled;
}
/**
 * @brief 设置Power Saving Mode状态
 *
 * @param mode true: 开启Power Saving Mode, false: 关闭Power Saving Mode
 * @return 设置成功返回NCI_STATUS_OK, 其他 设置失败
 */
tNCI_STATUS nfa_vs_set_power_saving_mode(bool mode) {
    GET_VS_LOCK(return NCI_STATUS_EXT_GET_LOCK_FAILED);
    uint8_t raw_nci[] = {0x2F, 0x0C, 0x02, NCI_ANDROID_POWER_SAVING, mode ? 0x01 : 0x00};
    tNCI_VS_CMD cmd = {
        .data = raw_nci,
        .len = sizeof(raw_nci),
    };
    tNCI_RSP rsp = {0};
    tNCI_STATUS ret = nfa_vs_send_cmd(&cmd, 1, &rsp, true, VS_RFST_RULE_ALLOW_ALL);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_vs_send_cmd failed, ret = %d", ret);
        goto unlock;
    }
    if (rsp.data && (rsp.len == NCI_ANDROID_PROP_RSP_LEN)) {
        ret = rsp.data[NCI_ANDROID_PROP_RSP_LEN - 1];
    } else {
        ret = NCI_STATUS_EXT_FAILED;
        NFCLOG_E("rsp data is invalid, len = %d", rsp.len);
    }
unlock:
    RELEASE_VS_LOCK();
    nfa_utils_free_rsp(&rsp, true);
    return ret;
}
/**
 * @brief 发送原始的Vendor Specific命令
 *
 * @param[in] mt 消息类型
 * @param[in] gid CMD组ID
 * @param[in] oid CMD操作ID
 * @param[in] p_payload CMD数据
 * @param[in] payload_len CMD数据长度
 * @param[out] p_rsp 接收rsp数据
 *
 * @note p_rsp需要调用者调用nfa_utils_free_rsp函数释放
 *
 * @return 发送成功返回NCI_STATUS_OK, 其他 发送失败
 */
tNCI_STATUS nfa_vs_send_raw_vendor_cmd(int mt, int gid, int oid, uint8_t *p_payload, uint16_t payload_len, tNCI_RSP *p_rsp) {
    OSI_CHK_PARAM_INVALID(!p_payload, return NCI_STATUS_INVALID_PARAM);
    OSI_CHK_PARAM_INVALID(payload_len == 0, return NCI_STATUS_INVALID_PARAM);
    OSI_CHK_PARAM_INVALID(!p_rsp, return NCI_STATUS_INVALID_PARAM);
    GET_VS_LOCK(return NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    uint8_t *p_nci_raw = osi_calloc(payload_len + NCI_BUF_HEAD_SIZE);
    if (!p_nci_raw) {
        NFCLOG_E("osi_calloc failed!");
        ret = NCI_STATUS_EXT_ALLOC_FAILED;
        goto unlock;
    }
    p_nci_raw[0] = ((mt & NCI_MT_MASK) << NCI_MT_SHIFT) | (gid & NCI_GID_MASK);
    p_nci_raw[1] = oid & NCI_OID_MASK;
    p_nci_raw[2] = payload_len;
    if (!osi_memcpy_s(p_nci_raw + NCI_BUF_HEAD_SIZE, payload_len, p_payload, payload_len)) {
        NFCLOG_E("osi_memcpy_s failed!");
        ret = NCI_STATUS_EXT_COPY_FAILED;
        goto unlock;
    }

    tNCI_VS_CMD cmd = {
        .data = p_nci_raw,
        .len = payload_len + NCI_BUF_HEAD_SIZE,
    };
    ret = nfa_vs_send_cmd(&cmd, 1, p_rsp, true, VS_RFST_RULE_ALLOW_ALL);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_vs_send_cmd failed, ret = %d", ret);
    }
unlock:
    RELEASE_VS_LOCK();
    if (p_nci_raw) {
        osi_free(p_nci_raw);
    }
    if (ret != NCI_STATUS_OK) {
        nfa_utils_free_rsp(p_rsp, true);
    }
    return ret;
}
/**
 * @brief 获取Vendor Specific的私有能力
 *
 * @param[out] p_rsp 接收rsp数据
 *
 * @note p_rsp需要调用者调用nfa_utils_free_rsp函数释放
 *
 * @return 获取成功返回NCI_STATUS_OK, 其他 获取失败
 */
tNCI_STATUS nfa_vs_get_proprietary_caps(tNCI_RSP *p_rsp) {
    OSI_CHK_PARAM_INVALID(!p_rsp, return NCI_STATUS_INVALID_PARAM);
    GET_VS_LOCK(return NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    uint8_t raw_nci[] = {0x2F, NCI_ANDROID_OID, 0x00};
    tNCI_VS_CMD cmd = {
        .data = raw_nci,
        .len = sizeof(raw_nci),
    };
    tNCI_RSP rsp = {0};
    ret = nfa_vs_send_cmd(&cmd, 1, &rsp, true, VS_RFST_RULE_ALLOW_ALL);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nfa_vs_send_cmd failed, ret = %d", ret);
        goto unlock;
    }
    if (!rsp.data || rsp.len <= NCI_ANDROID_PROP_RSP_LEN) {
        NFCLOG_E("rsp data is invalid, len = %d", rsp.len);
        ret = NCI_STATUS_EXT_FAILED;
        goto unlock;
    }
    ret = rsp.data[NCI_ANDROID_PROP_RSP_LEN - 1];
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("get proprietary caps failed, ret = %d", ret);
        goto unlock;
    }
    NFCLOG_D("get proprietary caps success");
    uint8_t cap_len = rsp.data[NCI_ANDROID_GET_CAP_INDEX_CAP_LEN];
    if ((cap_len == 0) || (rsp.len < (NCI_ANDROID_GET_CAP_INDEX_CAP_LEN + 1 + cap_len))) {
        NFCLOG_E("rsp data is invalid, len = %d", rsp.len);
        ret = NCI_STATUS_EXT_FAILED;
        goto unlock;
    }

    p_rsp->data = osi_calloc(cap_len);
    if (!p_rsp->data) {
        NFCLOG_E("osi_calloc failed!");
        ret = NCI_STATUS_EXT_ALLOC_FAILED;
        goto unlock;
    }
    if (!osi_memcpy_s(p_rsp->data, cap_len, rsp.data + NCI_ANDROID_GET_CAP_INDEX_CAP_LEN + 1, cap_len)) {
        NFCLOG_E("osi_memcpy_s failed!");
        ret = NCI_STATUS_EXT_COPY_FAILED;
        goto unlock;
    }
    p_rsp->len = cap_len;

unlock:
    RELEASE_VS_LOCK();
    nfa_utils_free_rsp(&rsp, true);
    if (ret != NCI_STATUS_OK) {
        nfa_utils_free_rsp(p_rsp, true);
    }
    return ret;
}

/**
 * @brief Vendor Specific管理模块初始化
 *
 * @param p_cfg 指向配置结构体的指针，用于传递初始化所需的配置信息
 *
 * @return 传输成功返回NCI_STATUS_OK，失败返回错误码
 */
static tNCI_STATUS vs_init(const tNCI_MODULE_INIT_CFG *p_cfg) {
    if (osi_mutex_init_with_attr(&s_vs.mutex, true) != NFC_STATUS_OK) {
        NFCLOG_E("osi_mutex_init failed");
        return NCI_STATUS_FAILED;
    }
    if ((!p_cfg) || (!p_cfg->p_external_cfg) || (!p_cfg->p_external_cfg->vs_cback)) {
        s_vs.ntf_upload_enable = false;
        NFCLOG_D("vs_cback is not registered");
    } else {
        s_vs.cback = p_cfg->p_external_cfg->vs_cback;
        s_vs.ntf_upload_enable = true;
    }
    return NCI_STATUS_OK;
}

/**
 * @brief Vendor Specific管理模块销毁
 *
 * @param is_shutdown 一个布尔值，表示是否是关机操作
 *
 * @return 只返回 NCI_STATUS_OK，表示操作成功
 */
static tNCI_STATUS vs_deinit(bool is_shutdown) {
    (void)is_shutdown;
    if (osi_mutex_deinit(&s_vs.mutex) != NFC_STATUS_OK) {
        NFCLOG_E("osi_mutex_deinit failed");
    }
    osi_memset_s(&s_vs, sizeof(s_vs), 0x00, sizeof(s_vs));
    return NCI_STATUS_OK;
}

/**
 * @brief Vendor Specific管理模块dump函数
 */
static void vs_dump(int fd) {
    osi_dump(fd, "ntf_upload_enable = %d", s_vs.ntf_upload_enable);
    osi_dump(fd, "observe_mode_enabled = %d", s_vs.observe_mode_enabled);
    osi_dump(fd, "proprietary_lxdebug = %d", s_vs.proprietary_lxdebug);
}

/**
 * @brief NFC Vendor Specific管理模块定义
 */
tNCI_MODULE g_vs_manager = {
    .name = "VS_MANAGER",
    .init = vs_init,
    .deinit = vs_deinit,
    .dump = vs_dump,
};
#endif // IS_FEATURE_ON(NCI_FEATURE_VS)
